package cn.wolfcode.rbac.web.interceptor;

import cn.wolfcode.rbac.domain.Employee;
import cn.wolfcode.rbac.util.R;
import cn.wolfcode.rbac.util.RedisKey;
import cn.wolfcode.rbac.util.RequirePermission;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

@Component
public class PermissionInterceptor implements HandlerInterceptor {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        /*1.通过请求头中token,获取Redis存储的员工对象。
        2.判断当前用户是不是管理员
                - 如果是管理员，不受权限控制，所有的方法都能访问
                - 如果不是管理员
                - 判断当前请求方法上是否有贴@RequirePermission注解
        - 如果没有，说明该方法并不需要权限控制，直接放行
                - 如果有, 从Redis中获取用户的权限集合,查看当前方法的表达式是否在用户的权限集合中
                - 如果在, 说明该用户已经被授予该功能的访问权限，直接放行即可
                - 如果不在, 该方法需要访问控制，但是当前用户并未授予该功能的访问权限，直接拒绝请求,返回错误信息{"code":"403","msg":"您没有权限访问"}*/
        String token = request.getHeader("token");
        String tokenKey = RedisKey.TOKEN_PREFIX+token;
        String objStr = stringRedisTemplate.opsForValue().get(tokenKey);
        Employee currentUser = JSON.parseObject(objStr,Employee.class);
        if(currentUser.getAdmin()){
            return true;
        }
        HandlerMethod method = (HandlerMethod) handler;
        RequirePermission rp = method.getMethodAnnotation(RequirePermission.class);
        if(rp==null){
            //说明方法上没有贴注解,直接放行
            return true;
        }
        //获取当前方法的表达式
        String expression = rp.expression();
        //判断是否在用户的集合中
        String permissionKey = RedisKey.USER_PERMISSION_LIST_PREFIX+currentUser.getId();
        String listStr = stringRedisTemplate.opsForValue().get(permissionKey);
        List<String> permissionList = JSON.parseArray(listStr,String.class);
        if(permissionList.contains(expression)){
            //说明用户有该表达式
            return true;
        }
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(JSON.toJSONString(R.fail(403,"您没有权限操作")));
        return false;
    }
}
